package com.market.plus.core.service.impl;


import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.market.plus.core.dao.NewsDao;
import com.market.plus.core.dao.NewsDb;
import com.market.plus.core.dao.ParticipantDao;
import com.market.plus.core.domain.Comment;
import com.market.plus.core.domain.News;
import com.market.plus.core.domain.NewsFriends;
import com.market.plus.core.domain.NewsSecurityType;
import com.market.plus.core.domain.NewsType;
import com.market.plus.core.domain.Participant;
import com.market.plus.core.domain.Status;
import com.market.plus.core.dto.CommentDto;
import com.market.plus.core.dto.NewsDto;
import com.market.plus.core.dto.ParticipantDto;
import com.market.plus.core.mapping.DTOConfiguration;
import com.market.plus.core.mapping.DTOService;
import com.market.plus.core.mapping.DomainService;
import com.market.plus.core.mapping.IDMapping;
import com.market.plus.core.service.MarketOCMService;
import com.market.plus.core.service.NewsService;
import com.market.plus.core.util.MarketUtil;

@Service("newsService")
@Transactional(readOnly = true)
public class NewsServiceImpl implements NewsService {

   private DomainService domainService;

   private DTOService dtoService;

   private NewsDao newsDao;

   private NewsDb jdbcNewsDao;

   private ParticipantDao participantDao;

   private MarketOCMService marketOCMService;

   @Autowired
   public NewsServiceImpl(
       @Qualifier("newsDao")NewsDao newsDao,
       @Qualifier("jdbcNewsDao")NewsDb jdbcNewsDao,
       @Qualifier("participantDao")ParticipantDao participantDao,
       @Qualifier("marketOCMService") MarketOCMService marketOCMService,
       @Qualifier("marketDomainService") DomainService domainService,
       @Qualifier("marketDtoService") DTOService dtoService) {
      this.newsDao = newsDao;
      this.jdbcNewsDao=jdbcNewsDao;
      this.domainService = domainService;
      this.dtoService = dtoService;
      this.participantDao = participantDao;
      this.marketOCMService = marketOCMService;
   }

   @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
   public String saveNews(NewsDto newsDto, Long particicipantId, NewsSecurityType newsSecurityType, long[] friendIds) throws Exception {
      News news = this.domainService.convertNews(newsDto);
      NewsFriends newsFriends = news.createNewsFriendsInts();
      long[] myFriends = null;
      switch (newsSecurityType) {
      case PUBLIC:
         news.setHasPublic(true);
         break;
      case ALLFRIENDS:
         List<Participant> friends = this.participantDao.findMyFriends(particicipantId);
         newsFriends.appendFriendId(particicipantId);
         myFriends = new long[friends.size()];
         for (int index=0; index<friends.size(); index++){
            Participant participant = friends.get(index);
            Long externalId = Long.parseLong(participant.getUserInfo().getExternalId());
            myFriends[index] = externalId;
            newsFriends.appendFriendId(participant.getId());
         }
         news.setHasPublic(false);
         break;
      case CUSTOM:
         news.setHasPublic(false);
         break;
      }
      Participant participant = this.participantDao.findById(particicipantId);
      news.setParticipant(participant);
      String newguid = this.marketOCMService.saveNews(participant, news, myFriends);
      news.setGuid(newguid);
      this.newsDao.save(news);
      return newguid;
   }

   public NewsDto getPersonalIntroduction(Long participantId) {
      NewsDto newsDto = null;
      News news = this.newsDao.findByParticipant(participantId, NewsType.PERSONAL);
      if (news != null)
         newsDto = this.dtoService.convertNewsDto(news, DTOConfiguration.instance(IDMapping.NEWS_LIMIT));
      return newsDto;
   }

   public List<NewsDto> getCommonNews(Long participantId) {
      List<News> news = this.jdbcNewsDao.getNews(participantId);
      List<NewsDto> newsDto = this.dtoService.convertNewsDto(news, DTOConfiguration.instance(IDMapping.PERSONAL_NEWS));
      return newsDto;
   }

   public List<NewsDto> getPrivateNews(Long participantId) {
      Participant participant = this.participantDao.findById(participantId);
      String[] newsGUID = this.marketOCMService.getNewGUIDs(participant.getGuid());
      List<News> news = this.newsDao.retrieveNews(participantId, newsGUID, NewsType.NEWS);
      List<NewsDto> newsDto = this.dtoService.convertNewsDto(news, DTOConfiguration.instance(IDMapping.PERSONAL_NEWS));
      List<NewsDto> orderableNewsDto = new ArrayList<NewsDto>();
      NewsDto expectedNewsDto = new NewsDto();
      for (String guid:newsGUID){
         expectedNewsDto.setGuid(guid);
         int index=newsDto.indexOf(expectedNewsDto);
         if (index>=0){
            orderableNewsDto.add(orderableNewsDto.size(),newsDto.get(index));
         }
      }
      return orderableNewsDto;
   }

   @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
   public void addComment(Long participantId, Long newsId, CommentDto commentDto) throws Exception{
      News news = this.newsDao.findById(newsId);
      if (news != null){
         String newsGUID = news.getGuid();
         Participant participant = this.participantDao.findById(participantId);
         ParticipantDto participantDto = new ParticipantDto();
         participantDto.setId(participant.getId());
         participantDto.setGuid(participant.getGuid());
         
         Comment comment = this.domainService.convertComment(commentDto);
         comment.setParticipant(participant);
         comment.setNews(news);

         List<Comment> latestComments = new ArrayList<Comment>();
         latestComments.add(comment);

         news.setComments(latestComments);

         MarketUtil.setModifyedUser(comment, Status.UPDATED);
         int totalComments = news.getTotalComments();
         totalComments++;
         news.setTotalComments(totalComments);
         this.newsDao.save(news);

         commentDto.setParticipantDto(participantDto);
         this.marketOCMService.comments(newsGUID, commentDto);
      }
   }

   public List<CommentDto> getComments(String newsGUID) {
      List<CommentDto> commentDtos = this.marketOCMService.getComment(newsGUID);
      for (CommentDto commentDto : commentDtos){
         ParticipantDto participantDto = commentDto.getParticipant();
         Participant participant = this.participantDao.findParticipantByGUID(participantDto.getGuid());
         participantDto = this.dtoService.convertParticipantDto(participant, null);
         commentDto.setParticipantDto(participantDto);
      }
      return commentDtos;
   }

   public List<NewsDto> filterByFriends(ParticipantDto participantDto, ParticipantDto[] friends) {
      List<NewsDto> newsDto = new ArrayList<NewsDto>();
      if (friends != null && friends.length > 0){
         List<Long> friendIds = new ArrayList<Long>();
         for (ParticipantDto friend : friends){
            friendIds.add(friend.getId());
         }
         List<News> news = this.jdbcNewsDao.getPrivateNews(participantDto.getId(), friendIds);
         newsDto = this.dtoService.convertNewsDto(news, DTOConfiguration.instance(IDMapping.PERSONAL_NEWS));
      }
      return newsDto;
   }
}
